package com.wocai.jrt.utils;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.security.Key;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.vteba.utils.common.PropsUtils;
import com.vteba.utils.cryption.RSAUtils;
import com.wocai.jrt.orders.bean.CallBackReqBean;

public class UnionPayCallbackUtils {
	private static final Logger LOGGER = LoggerFactory.getLogger(UnionPayCallbackUtils.class);
	private static final String desKey = PropsUtils.get("payCallback.deskey");
	private static final String publicKey = PropsUtils.get("payCallback.publickey");

	public UnionPayCallbackUtils() {

	}

	public static String parseToJsonString(String params) {
		byte[] desByte = null;
		try {
			desByte = desEdeEcbPkcs5Decrypt(hexString2ByteArr(params), desKey.getBytes());
		} catch (Exception e1) {
			LOGGER.error("解密参数错误，错误信息为：", e1.getMessage());
		}
		try {
			if (null == desByte) {
				return null;
			}
			return new String(desByte, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			LOGGER.error("parse byte to String error,", e.getMessage());
			return null;
		}
	}

	public static <T> Object parseToObject(String params, Class<T> type) {
		String paramJsonString = parseToJsonString(params);
		if (null == paramJsonString) {
			return null;
		}
		return JSON.parseObject(paramJsonString, type);
	}

	public static byte[] hexString2ByteArr(String hexStr) {
		if (hexStr == null)
			return null;
		if (hexStr.length() % 2 != 0) {
			return null;
		}
		byte[] data = new byte[hexStr.length() / 2];
		for (int i = 0; i < hexStr.length() / 2; i++) {
			char hc = hexStr.charAt(2 * i);
			char lc = hexStr.charAt(2 * i + 1);
			byte hb = hexChar2Byte(hc);
			byte lb = hexChar2Byte(lc);
			if (hb < 0 || lb < 0) {
				return null;
			}
			int n = hb << 4;
			data[i] = (byte) (n + lb);
		}
		return data;
	}

	public static byte hexChar2Byte(char c) {
		if (c >= '0' && c <= '9')
			return (byte) (c - '0');
		if (c >= 'a' && c <= 'f')
			return (byte) (c - 'a' + 10);
		if (c >= 'A' && c <= 'F')
			return (byte) (c - 'A' + 10);
		return -1;
	}

	public static byte[] desEdeEcbPkcs5Decrypt(byte[] data, byte[] keyData) throws Exception {
		if (keyData.length < 24)
			keyData = make3DesKey(keyData);
		Key localKey = makeDesKey(keyData);
		Cipher localCipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
		localCipher.init(Cipher.DECRYPT_MODE, localKey);
		return localCipher.doFinal(data);
	}

	private static final Key makeDesKey(byte[] keyData) throws Exception {
		DESedeKeySpec keySpec = new DESedeKeySpec(keyData);
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
		return keyFactory.generateSecret(keySpec);
	}

	private static byte[] make3DesKey(byte[] keyData) {
		byte[] key3 = null;
		byte[] key1 = new byte[8];
		ByteBuffer buf = ByteBuffer.wrap(keyData);
		buf.get(key1);
		buf.clear();
		buf = ByteBuffer.allocate(24);
		buf.put(keyData);
		buf.put(key1);
		buf.flip();
		key3 = buf.array();
		buf.clear();
		return key3;
	}

	public static Boolean verifySignature(String params, String signature) {
		String decodedString = "";
		try {
			decodedString = new String(RSAUtils.decode(signature, publicKey));
		} catch (Exception e) {
			LOGGER.error("签名解析失败", e.getMessage());
		}
		if (params.equals(decodedString)) {
			return true;
		} else {
			return false;
		}

	}

	public static boolean verify(byte[] data, String sign) {
		try {
			byte[] keyBytes = Base64.decodeBase64(publicKey);
			X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
			PublicKey publicK = keyFactory.generatePublic(keySpec);
			Signature signature = Signature.getInstance("SHA1withRSA");
			signature.initVerify(publicK);
			signature.update(data);
			// return signature.verify(Base64.decodeBase64(sign));
			return signature.verify(hexString2ByteArr(sign));
		} catch (Exception e) {
			return false;
		}
	}

	public static void main(String[] args) throws Exception {

		// 第三方提供的测试用例
		String params = "349591A75387E430339C49E2E7FD83D955B54C817E9A43762CE33F6322DEDF79F398C9106D350E6A3A128DC8A8F5A6704E48C73B23A91DD5DF75344D6EDFB1190881BC3CF42940C4E8BA97999EF8CF0A12F1EC1491BCB9FBCEFB690D05B82C192B957B8911B03373AB50EB66C8C10BE503896B6B1EFAB38E4E68BF1CFABFB5E4C7F043CEC1DEF4F70A99A650C9DC593A5CA05DA885AC4A05668CF4469D163044330056C41DF03286AEC3DE87F144DBC6F222B45AD45C9C3D4C0E6CCDC7BE86223D421110B024C5099A6438095DAE502CF55C9888AB99CD978DA52EA1BFF1BF3B0CA1280B0596535E6923261CC8BA3B4DE9EC9F9EC309E45895D7CDE362EF4EFA81703511372FB717A288B5ED0993A9A9509E6FAA3025AF2A5593EDACC1A83440F37ED67591F72FF5A774E18119F0CC005F2E6B635530582010CBD392DDB7EE111C7CADD04994C23080DC312D9338E489106519F23AD69756C2EB9ACC60D5954A7ABA976778B2107B35791AF3D6C49A768671923672EE6C52B376D6005142F7CB157EE67DA85D399D25D937F6F59497EB62861776A653F139D3BDB4DF5601651E3F26CC99F5ECF0299532DA7AC6DDB00F";
		String desKey = "cc3c40af69f269961a04163fd8251fd3";
		byte[] desByte = desEdeEcbPkcs5Decrypt(hexString2ByteArr(params), desKey.getBytes());
		System.out.println("收到的支付信息:" + new String(desByte, "UTF-8"));

		// 自己的测试
		params = "8612F080DD8A26131881D810EEF7A4181B1020E0CA761CF4DEB7A3FE501357DD76C1F32BA0F24C855FC0732BAC0409BA11A9F2D09E5284F73E6B1B9D0FF1B6237E1DFA80C8141FCE78D7F2B3CBC342ED900DC7656E0BBF4785DF8FD73AF7D48991E49E4D4D831E3A5586FA9565161BC09B42B6DC3AA8A0C701849C0BF1EF4EDF9B4D0DEB6E5D148286487B36EBE74288A36ECE4C0FB005C0243941A28791494AC38778305E2F0E1976208DFDBB4172EDF0807CBF90D68D4F8D93BC988C0409D73B3E22373B8D64535200FD9B983974B81BE067A1C7F2198258ED9F714B3EFD8180A58DD2EF727B28C60507EA8F91244E7E9DB7A0D1E8AB29B6DC3953340C69282004E77CAC604C8984B71AC95F1386851DED29606C4756D1088A36792DA2E51EB42A49E55416C7E6B35A16977B7F0A6B0E81437538C09E68D3A428ACCFAF9C49389C33122A9C9334EDFFDED220E503D5B1CF6A55F9552E17CB03EEAF752D31DAA924FC4EF08A3B4B58DCF987AA95B26C909BF7A7D088C03ADF7C9DFBE797301D4ACE8B832517A1676584830C29F8B0EF82A4BB516F660EE7694DC66E272FD449E14E93616EE75E5E500A1BC78A1305895A43457BAD853DB2";
		String signature = "86A17DD46B275B994A9D9C0E91A1D50BA1C1CA1685AB531CD116ABF627F72079C455082EACA1AEE4EC973D9BA389B1C9D043260140FAE34C905FDCB7D24C2E9C429C993085306AAD76566D43189D4B8D80209693BF8B822C39B96FE9218B87F8D96D87C6EF782D9D277263C4E6F60132419970B4D3DBF798D97E2586BCD0A311624B917F5922291B0A12858757E83B102763463183E5D7C9798F21AFEF0AE2C3EF59DF0703A518AEF48DF750ED3F366389CA135F6ED3608131D3E69D4F20EC1BCD37477047A58A1B0F26FECB15CBE020AFA7299E8F0713DFB112B70838C146DB8B68177E06839247058098E998B894F0A79629FDE8CFE59F110C211291B916F5";
		boolean verifyResult = verify(params.getBytes(), signature);
		System.out.println("验证支付信息:" + verifyResult);

		// 解密
		desKey = "f6cbb47b934cb5eb85f1594647e5d017";
		desByte = desEdeEcbPkcs5Decrypt(hexString2ByteArr(params), hexString2ByteArr(desKey));
		System.out.println("收到的支付信息:" + new String(desByte, "UTF-8"));
		System.out.println("收到的支付信息:"
				+ JSON.parseObject(new String(desByte, "UTF-8"), CallBackReqBean.class));

	}
}
